import os
import zipfile
from datetime import datetime
import xml.etree.ElementTree as ET

import requests
from loguru import logger

from dto.qunar_one_way_policy_request import *


# -*- coding: utf-8 -*-
# @Author : HJH
# @Time : 2024/1/23 10:19
# @Use : 去哪儿上传政策

def qn_process_row(row, pr_param, pr_dom):
    """
    定义一个函数，传入一行数据，转化为Policy需要导入的政策
    :param pr_param: 输入的参数
    :param pr_dom: 域名标识
    :param row:携程数据
    :return:去哪儿接口需要的Policy数据
    """
    if not isinstance(pr_param, dict):
        RuntimeError("输入参数有误，请检查后重新启动")

    is_share = 0
    if 'GX' in pr_param.get('platform', ''):
        is_share = 1

    policy = Policy()
    # 政策标识
    policy.policyCode = pr_param.get('policyCode').replace("*", "")
    if pr_param.get('policy_of_cabin') == 1:
        if row.get('cabin') in 'N,T,Z,V,E,H,U,L,A,M,B,Y':
            policy.policyCode = (pr_param.get('policyCode') + '0').replace("*", "")
        elif row.get('cabin') in 'R':
            policy.policyCode = (pr_param.get('policyCode') + '1').replace("*", "")
    # 政策有效性
    policy.status = '有效'
    # 航空公司
    policy.carrier = str(row.get('flightNo')[:2])
    policy.dpt = row.get('dep')
    # 出发机场
    policy.arr = row.get('arr')
    # 使用舱位
    policy.cabin = row.get('cabin')
    # 航班号限制
    policy.flightNoLimit = '适用'
    # 航班号
    policy.flightCondition = row.get('flightNo')
    # 支持共享航班
    policy.shared = '否' if is_share == 0 else '是'
    # 限制主飞航司
    if is_share == 1:
        shareFlightNo = row.get('shareFlightNo', None)
        policy.actCarrier = shareFlightNo[:2] if shareFlightNo else None
    # 支持经停航班
    policy.stop = '是'
    # 有效航班起飞日期起始
    policy.dptDateStart = row.get('depDate')
    # 有效航班起飞日期截止
    policy.dptDateEnd = row.get('depDate')
    # 班期限制
    policy.dayCondition = '1234567'
    # 产品类型
    policy.productMark = pr_param.get('productMark')
    if pr_dom == 'exw':
        # 产品类型
        # policy.productMark = '-1,201,221,223,227,894,514,497,504,501,891,505,431,503,574,493,502,225'
        # 可售卖范围
        policy.saleAvailable = '普通人群'
    elif pr_dom == 'fio':
        # 产品类型
        # policy.productMark = '280,989,354,356,551,698'
        # 可售卖范围
        policy.saleAvailable = '采购人群'
    # 支持儿童买成人
    policy.supportCba = '是'
    # 销售日期起始
    policy.saleDateStart = datetime.now().strftime("%Y-%m-%d")
    # 销售日期截止
    policy.saleDateEnd = datetime.now().replace(month=12, day=31, hour=23, minute=59,
                                                second=59).strftime("%Y-%m-%d")
    # 起飞前截止销售时间
    policy.lockTime = '120'
    # 最提前出票时限
    policy.earliestBeforeTicket = '365'
    # 最晚提前出票时限
    policy.beforeTicket = pr_param.get('beforeTicket')
    # 证件类型
    policy.cardType = pr_param.get('cardType')
    # 运价类型
    policy.printSource = '指定票面价'
    # 票面价
    policy.printPrice = str(int(float(row.get('costPrice'))) + pr_param.get('printPriceAdd', 0))
    # 票面价返点
    policy.printReturnPoint = '0'
    # 票面价留钱
    policy.printReturnPrice = '0'
    # 政策价返点
    policy.policyReturnPoint = '0'
    # 政策价留钱
    policy.policyReturnPrice = pr_param.get('policyReturnPrice')
    # 追价阈值
    policy.autoPriceThreshold = pr_param.get('autoPriceThreshold')
    # 百分比追价阈值
    policy.percentPriceThreshold = '0'
    # 预定 office 号
    policy.preOfficeNo = 'CGO104'
    # 是否生成PNR
    policy.needPnr = pr_param.get('needPnr')
    # 紧俏座位处理
    policy.highDemandType = pr_param.get('highDemandType')
    # 紧俏座位阈值
    policy.highDemandThreshold = pr_param.get('highDemandThreshold')
    # 是否进行PAT：A校验
    policy.needPata = '否'
    # 退票规则
    policy.returnRule = '0'
    # 改期规则
    policy.changeRule = '0'
    # 舱位说明
    policy.cabinNote = row.get('price').split('.')[0] + pr_param.get('policy_note')
    return policy


def add_qn_policy(policies: list, ap_dom: str):
    """
    单程统一政策上传参数
    :param ap_dom: 域名标识
    :param policies: 政策列表
    :return:
    """
    policy_list = PolicyList()
    # 用户名
    policy_list.username = 'dyzcwsw2819'
    # 密码
    policy_list.password = 'zhang123.'
    # 上传类型
    policy_list.execType = 'ADD'
    # 政策类型
    policy_list.type = 'SINGLE'
    # 扩展信息
    policy_list.ext = f'{ap_dom}去哪儿单程统一政策'
    # 回调地址
    policy_list.url = 'http://222.89.84.32:9095/feedback.jsp'

    root = ET.Element('PolicyList')
    # 转xml请求格式
    for key, value in vars(policy_list).items():
        root.set(key, value if value is not None else '')

    for item in policies:
        policy_xml = ET.SubElement(root, 'Policy')
        for key2, value2 in vars(item).items():
            policy_xml.set(key2, value2 if value2 is not None else '')

    xml_data = ET.tostring(root, encoding='utf-8', xml_declaration=True).decode('utf-8')
    # print(xml_data)
    return xml_data


def del_qn_policy(del_p_c, del_p_list):
    """
    单程统一政策删除参数
    :param del_p_list: 需要删除的政策，为空表示根据政策代码全删除
    :param del_p_c: 需要删除政策代码
    :return:
    """
    policy_list = PolicyList()
    # 用户名
    policy_list.username = 'dyzcwsw2819'
    # 密码
    policy_list.password = 'zhang123.'
    # 上传类型
    policy_list.execType = 'ADD'
    # 政策类型
    policy_list.type = 'SINGLE'
    # 扩展信息
    policy_list.ext = 'SINGLE'
    # 回调地址
    policy_list.url = 'http://222.89.84.32:9095/feedback.jsp'
    root = ET.Element('PolicyList')
    for key, value in vars(policy_list).items():
        root.set(key, value)

    if del_p_list is not None:
        for del_p in del_p_list:
            # 删除政策参数
            delete_policy = DeletePolicy()
            # 政策类型
            delete_policy.type = 'SINGLE'
            # 政策标识
            delete_policy.policyCode = del_p_c
            # 航空公司
            # delete_policy.flightcode = del_p.get('flightNo')[:2]
            # 出发地
            delete_policy.dpt = del_p.get('dep')
            # 目的地
            delete_policy.arr = del_p.get('arr')
            # 舱位
            # delete_policy.cabin = del_p.get('cabin')
            # 旅行起始日期
            delete_policy.startdate = del_p.get('depDate')
            # 旅行结束日期
            delete_policy.enddate = del_p.get('depDate')

            del_policy_xml = ET.SubElement(root, 'DeletePolicy')
            for key, value in vars(delete_policy).items():
                del_policy_xml.set(key, value if value is not None else '')
    else:
        # 删除政策参数
        delete_policy = DeletePolicy()
        # 政策类型
        delete_policy.type = 'SINGLE'
        # 政策标识
        delete_policy.policyCode = del_p_c
        del_policy_xml = ET.SubElement(root, 'DeletePolicy')
        for key, value in vars(delete_policy).items():
            del_policy_xml.set(key, value if value is not None else '')

    xml_data = ET.tostring(root, encoding='utf-8', xml_declaration=True).decode('utf-8')
    # print(xml_data)
    return xml_data


def send_qn_request(xml_params, sr_dom):
    # 1. 创建临时的 XML 文件并写入 xml_data
    xml_filename = f"{sr_dom}_policy.xml"  # XML 文件名
    zip_filename = f"{sr_dom}_policy.zip"  # ZIP 文件名
    with open(xml_filename, "w", encoding="utf-8") as file:
        file.write(xml_params)

    # 2. 创建一个空的 ZIP 文件
    with zipfile.ZipFile(zip_filename, "w") as zip_file:
        # 3. 将 XML 文件添加到 ZIP 文件中
        zip_file.write(xml_filename)

    # 4. 删除临时 XML 文件
    os.remove(xml_filename)

    url = f"https://{sr_dom}.trade.qunar.com/tts/interface/policy.jsp"

    # 使用 requests 发送 POST 请求并上传 ZIP 文件
    response = requests.post(url, open(zip_filename, "rb"))
    if response.status_code != 200:
        logger.error("【去哪儿请求异常】: {}", response.text)


def run_qn_gx_upload(ru_data_res, ru_param, domain):
    if not isinstance(ru_param, dict):
        RuntimeError("配置参数有误，请检查后重新启动")

    # 打开 JSON 文件
    with open('./config/share_flight.json') as f:
        # 加载 JSON 数据并转换为字典
        share_flight_data = json.load(f)

    policyDtoList = []
    share_platforms = ru_param.get('share_platform').split(',')
    copy_of_cabin = ru_param.get('copy_of_cabin', None)
    for item in ru_data_res:
        # 获取共享标识 整理出共享航班对
        share_flight = []
        for share_platform in share_platforms:
            if share_platform in share_flight_data:
                share_flight.extend(share_flight_data.get(share_platform))

        # 共享特殊处理
        share_flight = [sfd for sfd in share_flight if sfd['main_flight'] == item['flightNo']]

        for sf in share_flight:
            item['shareFlightNo'] = sf['main_flight']
            item['flightNo'] = sf['share_flight']

            # 根据舱位复制
            if not copy_of_cabin:
                cabins = copy_of_cabin.split(',')
                for cabin in cabins:
                    item['cabin'] = cabin
                    policyDto = qn_process_row(item, ru_param, domain)
                    policyDtoList.append(policyDto)
            else:
                policyDto = qn_process_row(item, ru_param, domain)
                policyDtoList.append(policyDto)

    size = 10000
    total = len(policyDtoList)
    logger.info(f"【上传{ru_param.get('platform')}政策数据长度】: {total}")
    if total == 0:
        return
    logger.info(f"【去哪儿{domain}GX单程统一上传政策】: 请求中... ...")
    for i in range(0, total, size):
        # 取出最大450条数据，添加到结果列表
        end = i + size
        subset = policyDtoList[i:end]
        # 获取请求参数
        add_req = add_qn_policy(subset, domain)
        send_qn_request(add_req, domain)

    logger.info(f"【去哪儿{domain}GX单程统一政策上传成功】: {ru_param.get('policyCode')}")


def run_qn_upload(ru_data_res, ru_param, domain):
    if not isinstance(ru_param, dict):
        RuntimeError("输入参数有误，请检查后重新启动")

    policyDtoList = []
    for item in ru_data_res:
        # 根据舱位复制
        if ru_param.get('copy_of_cabin', None) is not None:
            cabins = ru_param.get('copy_of_cabin').split(',')
            for cabin in cabins:
                item['cabin'] = cabin
                policyDto = qn_process_row(item, ru_param, domain)
                policyDtoList.append(policyDto)
        else:
            policyDto = qn_process_row(item, ru_param, domain)
            policyDtoList.append(policyDto)

    size = 10000
    total = len(policyDtoList)
    logger.info(f"【上传{ru_param.get('platform')}政策数据长度】: {total}")
    if total == 0:
        return
    logger.info(f"【去哪儿{domain}单程统一上传政策】: 请求中... ...")
    for i in range(0, total, size):
        # 取出最大450条数据，添加到结果列表
        end = i + size
        subset = policyDtoList[i:end]
        # 获取请求参数
        add_req = add_qn_policy(subset, domain)
        send_qn_request(add_req, domain)

    logger.info(f"【去哪儿{domain}单程统一政策上传成功】: {ru_param.get('policyCode')}")
